Package org.python.pydev.debug.newconsole

Source Code of org.python.pydev.debug.newconsole.PydevConsoleFactory

/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package org.python.pydev.debug.newconsole;

import java.io.IOException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.ui.console.IConsoleFactory;
import org.python.pydev.core.IInterpreterInfo;
import org.python.pydev.core.IPythonNature;
import org.python.pydev.core.log.Log;
import org.python.pydev.debug.core.PydevDebugPlugin;
import org.python.pydev.debug.model.PyDebugTargetConsole;
import org.python.pydev.debug.model.PyStackFrame;
import org.python.pydev.debug.model.remote.ListenConnector;
import org.python.pydev.debug.model.remote.RemoteDebuggerConsole;
import org.python.pydev.debug.newconsole.env.PydevIProcessFactory;
import org.python.pydev.debug.newconsole.env.PydevIProcessFactory.PydevConsoleLaunchInfo;
import org.python.pydev.debug.newconsole.env.JythonEclipseProcess;
import org.python.pydev.debug.newconsole.env.UserCanceledException;
import org.python.pydev.debug.newconsole.prefs.InteractiveConsolePrefs;
import org.python.pydev.editor.preferences.PydevEditorPrefs;
import org.python.pydev.plugin.preferences.PydevPrefs;

import com.aptana.interactive_console.InteractiveConsolePlugin;
import com.aptana.interactive_console.console.ui.ScriptConsoleManager;

/**
* Could ask to configure the interpreter in the preferences
*
* PreferencesUtil.createPreferenceDialogOn(null, preferencePageId, null, null)
*
* This is the class responsible for creating the console (and setting up the communication
* between the console server and the client).
*
* @author Fabio
*/
public class PydevConsoleFactory implements IConsoleFactory {

    /**
     * @see IConsoleFactory#openConsole()
     */
    public void openConsole() {
        createConsole(null);
    }

    /**
     * @return a new PydevConsole or null if unable to create it (user cancels it)
     */
    public void createConsole(String additionalInitialComands) {
        try {
            PydevConsoleInterpreter interpreter = createDefaultPydevInterpreter();
            if (interpreter == null) {
                return;
            }
            if (interpreter.getFrame() == null) {
                createConsole(interpreter, additionalInitialComands);
            } else {
                createDebugConsole(interpreter.getFrame(), additionalInitialComands);
            }
        } catch (Exception e) {
            Log.log(e);
        }
    }

    public void createConsole(final PydevConsoleInterpreter interpreter, final String additionalInitialComands) {

        Job job = new Job("Create Interactive Console") {

            @Override
            protected IStatus run(IProgressMonitor monitor) {
                monitor.beginTask("Create Interactive Console", 10);
                IStatus returnStatus = Status.OK_STATUS;
                try {
                    ScriptConsoleManager manager = ScriptConsoleManager.getInstance();
                    PydevConsole console;
                    if (interpreter.getFrame() == null) {
                        monitor.worked(1);
                        console = new PydevConsole(interpreter, additionalInitialComands);
                        monitor.worked(1);
                        try {
                            createDebugTarget(interpreter, console, new SubProgressMonitor(monitor, 8));
                        } catch (UserCanceledException uce) {
                            return Status.CANCEL_STATUS;

                        } catch (Exception e) {
                            //Just set the return status, but keep on going to add the console to the manager (as the message says).
                            returnStatus = PydevDebugPlugin
                                    .makeStatus(
                                            IStatus.ERROR,
                                            "Unable to connect debugger to Interactive Console\n"
                                                    + "The interactive console will continue to operate without the additional debugger features",
                                            e);
                        }
                        manager.add(console, true);
                    }

                } catch (Exception e) {
                    Log.log(e);
                    returnStatus = PydevDebugPlugin.makeStatus(IStatus.ERROR, "Error initializing console.", e);

                } finally {
                    monitor.done();
                }

                return returnStatus;
            }

        };
        job.setUser(true);
        job.schedule();
    }

    private void createDebugTarget(PydevConsoleInterpreter interpreter, PydevConsole console, IProgressMonitor monitor)
            throws IOException, CoreException, DebugException, UserCanceledException {
        monitor.beginTask("Connect Debug Target", 2);
        try {
            // Jython within Eclipse does not yet support these new features
            Process process = interpreter.getProcess();
            if (InteractiveConsolePrefs.getConsoleConnectVariableView() && !(process instanceof JythonEclipseProcess)) {
                PydevConsoleCommunication consoleCommunication = (PydevConsoleCommunication) interpreter
                        .getConsoleCommunication();

                try {
                    consoleCommunication.hello(new SubProgressMonitor(monitor, 1));
                } catch (Exception ex) {
                    try {
                        if (ex instanceof UserCanceledException) {
                            //Only close the console communication if the user actually cancelled (otherwise the user will expect it to still be working).
                            consoleCommunication.close();
                        }
                    } catch (Exception e) {
                        // Don't hide important information from user
                        Log.log(e);
                    }
                    if (ex instanceof UserCanceledException) {
                        UserCanceledException userCancelled = (UserCanceledException) ex;
                        throw userCancelled;
                    }
                    String message = "Unexpected error setting up the debugger connection. ";
                    if (ex instanceof SocketTimeoutException) {
                        message = "Timed out after " + InteractiveConsolePrefs.getMaximumAttempts()
                                + " attempts to connect to the console.";
                    }
                    throw new CoreException(PydevDebugPlugin.makeStatus(IStatus.ERROR, message, ex));
                }

                int acceptTimeout = PydevPrefs.getPreferences().getInt(PydevEditorPrefs.CONNECT_TIMEOUT);
                PyDebugTargetConsole pyDebugTargetConsole = null;
                IProcess eclipseProcess = interpreter.getLaunch().getProcesses()[0];
                RemoteDebuggerConsole debugger = new RemoteDebuggerConsole();
                ListenConnector connector = new ListenConnector(acceptTimeout);
                debugger.startConnect(connector);
                pyDebugTargetConsole = new PyDebugTargetConsole(consoleCommunication, interpreter.getLaunch(),
                        eclipseProcess, debugger);

                Socket socket = null;
                try {
                    consoleCommunication.connectToDebugger(connector.getLocalPort());
                    socket = debugger.waitForConnect(monitor, process, eclipseProcess);
                    if (socket == null) {
                        throw new UserCanceledException("Cancelled");
                    }
                } catch (Exception ex) {
                    try {
                        if (ex instanceof UserCanceledException) {
                            //Only close the console communication if the user actually cancelled (otherwise the user will expect it to still be working).
                            consoleCommunication.close();
                            debugger.dispose(); //Can't terminate the process either!
                        } else {
                            //But we still want to dispose of the connector.
                            debugger.disposeConnector();
                        }
                    } catch (Exception e) {
                        // Don't hide important information from user
                        Log.log(e);
                    }
                    if (ex instanceof UserCanceledException) {
                        UserCanceledException userCancelled = (UserCanceledException) ex;
                        throw userCancelled;
                    }
                    String message = "Unexpected error setting up the debugger";
                    if (ex instanceof SocketTimeoutException) {
                        message = "Timed out after " + Float.toString(acceptTimeout / 1000)
                                + " seconds while waiting for python script to connect.";
                    }
                    throw new CoreException(PydevDebugPlugin.makeStatus(IStatus.ERROR, message, ex));
                }

                pyDebugTargetConsole.startTransmission(socket); // this starts reading/writing from sockets
                pyDebugTargetConsole.initialize();

                consoleCommunication.setDebugTarget(pyDebugTargetConsole);
                interpreter.getLaunch().addDebugTarget(pyDebugTargetConsole);
                ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
                launchManager.addLaunch(interpreter.getLaunch());

                pyDebugTargetConsole.setConsole(console);
                console.setProcess(pyDebugTargetConsole.getProcess());
                pyDebugTargetConsole.finishedInit = true;
            }
        } finally {
            monitor.done();
        }
    }

    /**
     * Create a new Debug Console
     *
     * @param interpreter
     * @param additionalInitialComands
     */
    public void createDebugConsole(PyStackFrame frame, String additionalInitialComands) throws Exception {
        PydevConsoleLaunchInfo launchAndProcess = new PydevConsoleLaunchInfo(null, null, 0, null, frame);

        PydevConsoleInterpreter interpreter = createPydevDebugInterpreter(launchAndProcess);
        ScriptConsoleManager manager = ScriptConsoleManager.getInstance();
        PydevDebugConsole console = new PydevDebugConsole(interpreter, additionalInitialComands);
        manager.add(console, true);
    }

    /**
     * @return A PydevConsoleInterpreter with its communication configured.
     *
     * @throws CoreException
     * @throws IOException
     * @throws UserCanceledException
     */
    public static PydevConsoleInterpreter createDefaultPydevInterpreter() throws Exception, UserCanceledException {

        //            import sys; sys.ps1=''; sys.ps2=''
        //            import sys;print >> sys.stderr, ' '.join([sys.executable, sys.platform, sys.version])
        //            print >> sys.stderr, 'PYTHONPATH:'
        //            for p in sys.path:
        //                print >> sys.stderr,  p
        //
        //            print >> sys.stderr, 'Ok, all set up... Enjoy'

        PydevIProcessFactory iprocessFactory = new PydevIProcessFactory();

        PydevConsoleLaunchInfo launchAndProcess = iprocessFactory.createInteractiveLaunch();
        if (launchAndProcess == null) {
            return null;
        }
        if (launchAndProcess.interpreter != null) {
            return createPydevInterpreter(launchAndProcess, iprocessFactory.getNaturesUsed());
        } else {
            return createPydevDebugInterpreter(launchAndProcess);
        }

    }

    // Use IProcessFactory to get the required tuple
    public static PydevConsoleInterpreter createPydevInterpreter(PydevConsoleLaunchInfo info,
            List<IPythonNature> natures) throws Exception {
        final ILaunch launch = info.launch;
        Process process = info.process;
        Integer clientPort = info.clientPort;
        IInterpreterInfo interpreterInfo = info.interpreter;
        if (launch == null) {
            return null;
        }

        PydevConsoleInterpreter consoleInterpreter = new PydevConsoleInterpreter();
        int port = Integer.parseInt(launch.getAttribute(PydevIProcessFactory.INTERACTIVE_LAUNCH_PORT));
        consoleInterpreter.setConsoleCommunication(new PydevConsoleCommunication(port, process, clientPort));
        consoleInterpreter.setNaturesUsed(natures);
        consoleInterpreter.setInterpreterInfo(interpreterInfo);
        consoleInterpreter.setLaunch(launch);
        consoleInterpreter.setProcess(process);

        InteractiveConsolePlugin.getDefault().addConsoleLaunch(launch);

        consoleInterpreter.addCloseOperation(new Runnable() {
            public void run() {
                InteractiveConsolePlugin.getDefault().removeConsoleLaunch(launch);
            }
        });
        return consoleInterpreter;

    }

    /**
     * Initialize Console Interpreter and Console Communication for the Debug Console
     */
    public static PydevConsoleInterpreter createPydevDebugInterpreter(PydevConsoleLaunchInfo info) throws Exception {

        PyStackFrame frame = info.frame;

        PydevConsoleInterpreter consoleInterpreter = new PydevConsoleInterpreter();
        consoleInterpreter.setFrame(frame);

        // pydev console uses running debugger as a backend
        consoleInterpreter.setConsoleCommunication(new PydevDebugConsoleCommunication());
        return consoleInterpreter;
    }
}
TOP

Related Classes of org.python.pydev.debug.newconsole.PydevConsoleFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.